﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CodeMonkey.Utils;
using UnityEngine.EventSystems;
using System;


public class Grid<TGridObject>
{
    private int width;
    private int height;
    private float cellSize;

    public bool isDebug=false;


    private TGridObject[,] grids;
    private TextMesh[,] texts;

    private Vector3 origion;

    public const int HeapMapMaxValue = 100;
    public const int HeapMapMinValue = 0;

    //当数值发生变动时的事件
    public event EventHandler<OnGridValueChangeEventArgs> onGridValueChange;
    public class OnGridValueChangeEventArgs:EventArgs
    {
        public int x;
        public int y;
    }


    public Grid(int width, int height, float cellSize,Vector3 origion,Func<Grid<TGridObject>,int,int,TGridObject> onCreateData)
    {
        this.width = width;
        this.height = height;
        this.cellSize = cellSize;
        this.origion = origion;


        grids = new TGridObject[width, height];
        texts = new TextMesh[width, height];

        for (int i = 0; i < grids.GetLength(0); i++)
        {
            for (int j = 0; j < grids.GetLength(1); j++)
            {
                grids[i, j] = onCreateData(this,i,j);
            }
        }



       if (isDebug)
        {
            DrawGrid();
        }

    }

    private void DrawGrid()
    {
        GameObject parent = new GameObject("origion");
        parent.transform.localPosition = origion;
        for (int i = 0; i < grids.GetLength(0); i++)
        {
            for (int j = 0; j < grids.GetLength(1); j++)
            {
                //创建字体
                  texts[i,j]=UtilsClass.CreateWorldText(grids[i,j]?.ToString(),null,
                   GetWorldPosition(i,j)+new Vector3(cellSize,cellSize)*0.5f,20,null,TextAnchor.MiddleCenter);
                
                texts[i, j].transform.parent = parent.transform;
                //横线
                Debug.DrawLine(GetWorldPosition(i, j), GetWorldPosition(i + 1, j), Color.white, 100f);
                //竖线
                Debug.DrawLine(GetWorldPosition(i, j), GetWorldPosition(i, j+1), Color.white, 100f);
            }
        }

      
        Debug.DrawLine(GetWorldPosition(0,height), GetWorldPosition(width, height), Color.white, 100f);
      
        Debug.DrawLine(GetWorldPosition(width, 0), GetWorldPosition(width, height), Color.white, 100f);

        onGridValueChange += (object sender, OnGridValueChangeEventArgs e)=> 
        {
            texts[e.x, e.y].text= grids[e.x, e.y]?.ToString();
        };

    }


    public int GetWidth()
    {
        return width;
    }

    public int GetHeight()
    { 
        return height;
    }
    
    public float GetCellSize()
    {
        return cellSize;
    }

    public int GetHeatMapMax()
    {
        return HeapMapMaxValue;
    }


    public Vector3 GetWorldPosition(int x, int y)
    { 
        return new Vector3(x, y, 0)*cellSize+origion;
    }

    public void GetXY(Vector3 worldPosition, out int x, out int y)
    {
        x = Mathf.FloorToInt((worldPosition-origion).x/cellSize);
        y = Mathf.FloorToInt((worldPosition-origion).y/cellSize);
        
    }

    public void SetValue(Vector3 worldPosition, TGridObject value)
    {
        int x, y;
        GetXY(worldPosition, out x, out y);

        SetValue(x, y, value);

    }


    private void SetValue(int x, int y, TGridObject value)
    {
        if (!IsArea(x, y)) return;
        grids[x, y] = value;

        //有人订阅了这个事件
        if (onGridValueChange != null)
        {
            OnGridValueChangeEventArgs e = new OnGridValueChangeEventArgs();
            e.x = x;
            e.y = y;
            onGridValueChange(this, e);
            //onGridValueChange(this, new OnGridValueChangeEventArgs() { x = x, y = y });
        }
    }

    public void OnTriggerChange(int x,int y)
    {
        
        //有人订阅了这个事件
        if (onGridValueChange != null)
        {
            OnGridValueChangeEventArgs e = new OnGridValueChangeEventArgs();
            e.x = x;
            e.y = y;
            onGridValueChange(this, e);

        }
        //onGridValueChange(this, new OnGridValueChangeEventArgs() { x = x, y = y });
    }



    //通过鼠标点击获取当前位置的值
    public TGridObject GetGridObject(Vector3 worldPosition)
    {
        int x, y;
        GetXY(worldPosition, out x, out y);
        return GetGridObject(x, y);
    }


    public TGridObject GetGridObject(int x, int y)
    {
        if (IsArea(x, y))
        {
            return grids[x, y];
        }
        else
        {
            return default(TGridObject); 
        }
    }

    public bool IsArea(int x, int y)
    {
        return x >= 0 && x < width && y >= 0 && y < height;
    }


    //热力图
    //public void AddValue(Vector3 worldPosition,int fullValue,int fullRange,int totalRange)
    //{
    //    GetXY(worldPosition, out int originX, out int originY);

    //    int lowerValue = Mathf.RoundToInt(fullValue / (totalRange - fullRange));
       

    //    for (int i = 0; i < totalRange; i++)
    //    {
    //        for (int j = 0; j < totalRange-i; j++)
    //        {

    //            int radius = i + j;
    //            int addValue = fullValue;
    //            if (radius > fullRange)
    //            {
    //                addValue -= lowerValue * (radius - fullRange);
    //            }

    //            //右上角三角形
    //            int curX = originX + i;
    //            int curY = originY + j;
    //            SetValue(curX, curY, GetValue(curX, curY) + addValue);

    //            //左上角三角形
    //            curX = originX - i;
    //            curY = originY + j;
    //            if (i != 0)
    //            {
    //                SetValue(curX, curY, GetValue(curX, curY) + addValue);
    //            }

    //            if (j != 0)
    //            {
    //                curX = originX + i;
    //                curY = originY - j;
    //                SetValue(curX, curY, GetValue(curX, curY) + addValue);

    //                if (i != 0)
    //                {
    //                    curX = originX - i;
    //                    curY = originY - j;
    //                    SetValue(curX, curY, GetValue(curX, curY) + addValue);
    //                }
    //            }

    //        }
    //    }
    //}
}
